{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n",
        "什么是Pytorch\n",
        "================\n",
        "\n",
        "这是一个基于Python的科学计算软件包，面向两组受众：\n",
        "\n",
        "-  替代NumPy以使用GPU的功能\n",
        "-  深度学习研究平台，可提供最大的灵活性和速度\n",
        "\n",
        "开始吧\n",
        "---------------\n",
        "\n",
        "## 张量(Tensors)\n",
        "\n",
        "张量与NumPy的ndarrays类似，此外，  \n",
        "张量也可以在GPU上使用以加速计算。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "from __future__ import print_function\nimport torch"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "创建一个未初始化的5x3矩阵：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 3,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[-1.8736e-02,  5.3810e-43, -1.8736e-02],\n        [ 5.3810e-43, -1.8736e-02,  5.3810e-43],\n        [-1.8736e-02,  5.3810e-43, -1.8736e-02],\n        [ 5.3810e-43, -1.8736e-02,  5.3810e-43],\n        [-1.8736e-02,  5.3810e-43, -1.8736e-02]])\n"
        }
      ],
      "source": [
        "x = torch.empty(5, 3)\nprint(x)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "创建一个随机初始化的矩阵：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[0.1884, 0.9676, 0.0932],\n        [0.0237, 0.8706, 0.1165],\n        [0.8923, 0.6846, 0.2428],\n        [0.1050, 0.1057, 0.4467],\n        [0.2271, 0.8529, 0.5744]])\n"
        }
      ],
      "source": [
        "x = torch.rand(5, 3)\nprint(x)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "构造一个填充零且dtype long的矩阵：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[0, 0, 0],\n        [0, 0, 0],\n        [0, 0, 0],\n        [0, 0, 0],\n        [0, 0, 0]])\n"
        }
      ],
      "source": [
        "x = torch.zeros(5, 3, dtype=torch.long)\nprint(x)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "直接从数据创建张量：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([5.5000, 3.0000])\n"
        }
      ],
      "source": [
        "x = torch.tensor([5.5, 3])\nprint(x)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "或基于现有张量创建张量。 这些方法将重复使用输入张量的属性，例如dtype，除非用户提供新值\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 7,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[1., 1., 1.],\n        [1., 1., 1.],\n        [1., 1., 1.],\n        [1., 1., 1.],\n        [1., 1., 1.]], dtype=torch.float64)\ntensor([[-0.6246, -0.3308,  1.0961],\n        [-0.2643, -1.9371, -0.7324],\n        [-1.0433,  1.8659, -0.2630],\n        [-0.5869, -0.8914,  1.2099],\n        [-0.7889,  0.0762,  0.3997]])\n"
        }
      ],
      "source": [
        "x = x.new_ones(5, 3, dtype=torch.double)      # new_* methods take in sizes\nprint(x)\n\nx = torch.randn_like(x, dtype=torch.float)    # override dtype!\nprint(x)                                      # result has the same size"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "打印它的大小：\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 8,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "torch.Size([5, 3])\n"
        }
      ],
      "source": [
        "print(x.size())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-info\"><h4>注</h4><p>\n",
        "\n",
        "``torch.Size`` 实际上是一个tuple，因此它支持所有tuple操作。</p></div>\n",
        "\n",
        "## 运算(Operations)\n",
        "\n",
        "运算有多种语法实现。在下面的示例中，我们将看一下加法运算。\n",
        "\n",
        "加法：语法1\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[-0.5411, -0.2331,  1.4236],\n        [ 0.4124, -1.0028, -0.6942],\n        [-0.5186,  2.3691,  0.6042],\n        [-0.3107, -0.7324,  1.7120],\n        [-0.5278,  0.2224,  1.1851]])\n"
        }
      ],
      "source": [
        "y = torch.rand(5, 3)\nprint(x + y)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "加法：语法2\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[-0.5411, -0.2331,  1.4236],\n        [ 0.4124, -1.0028, -0.6942],\n        [-0.5186,  2.3691,  0.6042],\n        [-0.3107, -0.7324,  1.7120],\n        [-0.5278,  0.2224,  1.1851]])\n"
        }
      ],
      "source": [
        "print(torch.add(x, y))"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "加法：提供输出张量作为参数(argument)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[-0.5411, -0.2331,  1.4236],\n        [ 0.4124, -1.0028, -0.6942],\n        [-0.5186,  2.3691,  0.6042],\n        [-0.3107, -0.7324,  1.7120],\n        [-0.5278,  0.2224,  1.1851]])\n"
        }
      ],
      "source": [
        "result = torch.empty(5, 3)\ntorch.add(x, y, out=result)\nprint(result)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "加法：就地(in-place)\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([[-0.5411, -0.2331,  1.4236],\n        [ 0.4124, -1.0028, -0.6942],\n        [-0.5186,  2.3691,  0.6042],\n        [-0.3107, -0.7324,  1.7120],\n        [-0.5278,  0.2224,  1.1851]])\n"
        }
      ],
      "source": [
        "# adds x to y\ny.add_(x)\nprint(y)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "<div class=\"alert alert-info\"><h4>注</h4><p>\n",
        "\n",
        "任何使张量就地发生变化的操作都将使用 ``_``.\n",
        "    如: ``x.copy_(y)``, ``x.t_()``, 会改变 ``x``.</p></div>\n",
        "\n",
        "您可以使用类似NumPy的标准索引来变出各种花样！\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([-0.3308, -1.9371,  1.8659, -0.8914,  0.0762])\n"
        }
      ],
      "source": [
        "print(x[:, 1])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "调整大小：如果要调整张量的大小/形状，可以使用 ``torch.view``:\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "torch.Size([4, 4]) torch.Size([16]) torch.Size([2, 8])\n"
        }
      ],
      "source": [
        "x = torch.randn(4, 4)\ny = x.view(16)\nz = x.view(-1, 8)  # the size -1 is inferred from other dimensions\nprint(x.size(), y.size(), z.size())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "如果您具有一个元素张量，请使用``.item()``获取该值作为Python数字。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([0.5033])\n0.5032538771629333\n"
        }
      ],
      "source": [
        "x = torch.randn(1)\nprint(x)\nprint(x.item())"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "**稍后阅读:**\n",
        "\n",
        "  [这里](https://pytorch.org/docs/torch)\n",
        "  \n",
        "包含了100多个Tensor运算，包括转置(transposing)、索引(indexing)、分割(slicing)、数学运算(mathematical operations)、线性代数(linear algebra)、随机数(random numbers)等。\n",
        "\n",
        "NumPy转换\n",
        "------------\n",
        "\n",
        "将Torch张量转换为NumPy数组，反之亦然，这十分简单。\n",
        "\n",
        "Torch张量和NumPy数组将共享其基础内存位置，并且更改一个将更改另一个。\n",
        "\n",
        "## 将Torch张量转换为NumPy数组\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([1., 1., 1., 1., 1.])\n"
        }
      ],
      "source": [
        "a = torch.ones(5)\nprint(a)"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "[1. 1. 1. 1. 1.]\n"
        }
      ],
      "source": [
        "b = a.numpy()\nprint(b)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "看看numpy数组的值如何变化。\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([2., 2., 2., 2., 2.])\n[2. 2. 2. 2. 2.]\n"
        }
      ],
      "source": [
        "a.add_(1)\nprint(a)\nprint(b)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 将NumPy数组转换为Torch张量\n",
        "\n",
        "查看更改numpy数组如何自动更改Torch Tensor\n",
        "\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "[2. 2. 2. 2. 2.]\ntensor([2., 2., 2., 2., 2.], dtype=torch.float64)\n"
        }
      ],
      "source": [
        "import numpy as np\na = np.ones(5)\nb = torch.from_numpy(a)\nnp.add(a, 1, out=a)\nprint(a)\nprint(b)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "除CharTensor之外，CPU上的所有张量都支持转换为NumPy并转回。\n",
        "\n",
        "CUDA张量\n",
        "------------\n",
        "\n",
        "张量可以使用``.to``方法移动到任何设备上。\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "collapsed": false
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": "tensor([1.5033], device='cuda:0')\ntensor([1.5033], dtype=torch.float64)\n"
        }
      ],
      "source": [
        "# 让我们仅在CUDA可用时运行此单元格\n",
        "# 我们将使用``torch.device``对象将张量移入和移出GPU\n",
        "if torch.cuda.is_available():\n",
        "    device = torch.device(\"cuda\")          # CUDA设备对象\n",
        "    y = torch.ones_like(x, device=device)  # 在GPU上直接创建张量\n",
        "    x = x.to(device)                       # 或只使用字符串``.to(\"cuda\")``\n",
        "    z = x + y\n",
        "    print(z)\n",
        "    print(z.to(\"cpu\", torch.double))       # ``.to`` 也可以一起改变dtype！"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.8.3-candidate"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}